/*=============================================================================
PostEffects.h : Post process effects
Copyright (c) 2001 Crytek Studios. All Rights Reserved.

Revision history:
* 18/06/2005: Re-organized (to minimize code dependencies/less annoying compiling times)
* Created by Tiago Sousa
=============================================================================*/

#ifndef _POSTEFFECTS_H_
#define _POSTEFFECTS_H_

#include "PostProcessUtils.h"

struct SColorGradingMergeParams;
class CSoundEventsListener;

////////////////////////////////////////////////////////////////////////////////////////////////////
// Engine specific post-effects
////////////////////////////////////////////////////////////////////////////////////////////////////

struct SObjMotionBlurParams
{	
	SObjMotionBlurParams() : pRenderObj(NULL), nFrameUpdateID(0)
	{}

	SObjMotionBlurParams(CRenderObject* pObj, const Matrix34A& objToWorld, uint32 frameUpdateID)
	: pRenderObj(pObj), mObjToWorld(objToWorld), nFrameUpdateID(frameUpdateID) {}

	CRenderObject *pRenderObj;
	Matrix34A mObjToWorld;
	uint32 nFrameUpdateID;
};

// Camera + Object motion blur handling
class CMotionBlur: public CPostEffect
{
public:
  CMotionBlur()
  {          
    m_nRenderFlags = 0;
    m_nID = ePFX_eMotionBlur;

    // Register technique instance and it's parameters
    AddParamBool("MotionBlur_Active", m_pActive, 0);
    AddParamInt("MotionBlur_Type", m_pType, 0);
    AddParamInt("MotionBlur_Quality", m_pQuality, 1); // 0 = low, 1 = med, 2= high, 3= ultra-high, 4= crazy high, and so on
    AddParamFloat("MotionBlur_Amount", m_pAmount, 0.0f);
    AddParamFloatNoTransition("MotionBlur_FocusRange", m_pFocusRange, 1.0f);
    AddParamBool("MotionBlur_UseMask", m_pUseMask, 0);
    AddParamTex("MotionBlur_MaskTexName", m_pMaskTex, 0);
    AddParamFloat("MotionBlur_CameraSphereScale", m_pCameraSphereScale, 2.0f); // 2 meters by default
    AddParamFloat("MotionBlur_ExposureTime", m_pExposureTime, 0.004f);
    AddParamFloat("MotionBlur_VectorsScale", m_pVectorsScale, 1.5f);
		AddParamFloatNoTransition("MotionBlur_UserVectorsScale", m_pUserVectorsScale, 1.0f);
    AddParamFloat("MotionBlur_ChromaShift", m_pChromaShift, 0.0f);  // chroma shift amount
	AddParamFloat("MotionBlur_DrawNearZRangeOverride", m_pDrawNearZRangeOverride, 0.0f);

		AddParamFloatNoTransition("FilterRadialBlurring_Amount", m_pRadBlurAmount, 0.0f);
		AddParamFloatNoTransition("FilterRadialBlurring_ScreenPosX", m_pRadBlurScreenPosX, 0.5f);
		AddParamFloatNoTransition("FilterRadialBlurring_ScreenPosY", m_pRadBlurScreenPosY, 0.5f);
		AddParamFloatNoTransition("FilterRadialBlurring_Radius", m_pRadBlurRadius, 1.0f);  
		AddParamTex("FilterRadialBlurring_MaskTexName", m_pRadialBlurMaskTex, 0);      
		AddParamFloat("FilterRadialBlurring_MaskUVScaleX", m_pRadialBlurMaskUVScaleX, 1.0f);
		AddParamFloat("FilterRadialBlurring_MaskUVScaleY", m_pRadialBlurMaskUVScaleY, 1.0f);

		m_pVectorGenTechName = "MotionBlurVectorGen";
		m_pVectorGenOptTechName = "MotionBlurVectorGenOpt";		
		m_pMotionBlurDofTechName = "MotionBlurDof";
		m_pMotionBlurDisplTechName = "MotionBlurDispl";
		m_pMotionBlurRefTechName = "MotionBlurRef";

		m_pRefDofMBNormalize = "RefDofMbNormalizePass";

		m_pViewProjPrevParam = "mViewProjPrev";
		m_pViewProjParam = "mViewProj";

		m_pVSMotionBlurParams = "vsMotionBlurParams";

		m_pDiretionalBlurParamName = "vDirectionalBlur";
		m_pMotionBlurParamsName = "motionBlurParams";
		m_pDofFocusParam0Name = "vDofParamsFocus0";
		m_pDofFocusParam1Name = "vDofParamsFocus1";
		m_pRadBlurParamName = "vRadBlurParam";

		m_pMotionBlurParamName = "vMotionBlurParams";

		// annoying workaround due to arrays of constants not properly working on ps3..
		m_pViewReprojParamName[0] = "mViewReProj0";
		m_pViewReprojParamName[1] = "mViewReProj1";
		m_pViewReprojParamName[2] = "mViewReProj2";
		m_pViewReprojParamName[3] = "mViewReProj3";
		
		// annoying workaround due to arrays of constants not properly working on ps3..
		m_pParamLensSamplesName[0] = "vLensSamples0";
		m_pParamLensSamplesName[1] = "vLensSamples1";
		m_pParamLensSamplesName[2] = "vLensSamples2";
		m_pParamLensSamplesName[3] = "vLensSamples3";
		m_pParamLensSamplesName[4] = "vLensSamples4";
		m_pParamLensSamplesName[5] = "vLensSamples5";
		m_pParamLensSamplesName[6] = "vLensSamples6";
		m_pParamLensSamplesName[7] = "vLensSamples7";
		m_pParamLensSamplesName[8] = "vLensSamples8";
		m_pParamLensSamplesName[9] = "vLensSamples9";
		m_pParamLensSamplesName[10] = "vLensSamples10";
		m_pParamLensSamplesName[11] = "vLensSamples11";
		m_pParamLensSamplesName[12] = "vLensSamples12";
		m_pParamLensSamplesName[13] = "vLensSamples13";
		m_pParamLensSamplesName[14] = "vLensSamples14";
		m_pParamLensSamplesName[15] = "vLensSamples15";
		m_pParamLensSamplesName[16] = "vLensSamples16";
		m_pParamLensSamplesName[17] = "vLensSamples17";

    m_bResetPrevScreen = 1;
    m_fPrevFrameTime = 0;
    
		m_fRotationAcc = 0.0f;		
		m_nSamplesInfo = 0;		
		m_fRotSamplesEst = 0.0f;
		m_fTransSamplesEst = 0.0f;
		m_mScaleBias = Matrix44A(	0.5f,     0,	 0,   0,
																 0,	-0.5f,   0,   0,
																 0,		  0,	 1.0f,   0,						
															0.5f,	 0.5f,   0,   1.0f);

		m_nBokehQuadTaps = 0;
		m_pBokehQuadMesh = 0;
		m_pBokehShape = 0;
		m_nBokehMeshWidth = 0;
		m_nBokehMeshHeight = 0;
  }

  virtual ~CMotionBlur()
  {
    Release();
  }

	virtual int Initialize();
	virtual int CreateResources();
  virtual void Release();	

  virtual void Render();
	void RenderFullRes();		// Original full resolution rendering approach

	void MotionVectorsGen();
	float GetShutterSpeed();
	
  virtual void Reset(bool bOnSpecChange = false);
  virtual bool Preprocess();
	virtual void OnBeginFrame();
  	
	static void SetupObject( CRenderObject *pObj );
	static const Matrix34A& GetPrevObjToWorldMat( CRenderObject *pObj );
	static Matrix44A &GetPrevView()
	{
		const uint32 nThreadID = gRenDev->m_RP.m_nProcessThreadID;
# ifndef _RELEASE
   if (SRendItem::m_RecurseLevel[nThreadID]==0) __debugbreak();
# endif
		return gRenDev->m_CameraMatrixPrev;//[nThreadID][ min(1, SRendItem::m_RenderView[nThreadID][SRendItem::m_RecurseLevel[nThreadID] - 1]) ];
	}

  virtual const char *GetName() const
  {		
		return CRenderer::CV_r_UseMergedPosts? "MotionBlur and Dof" : "MotionBlur";
  }

private:

	CCryNameTSCRC m_pVectorGenTechName;
	CCryNameTSCRC m_pVectorGenOptTechName;
	CCryNameTSCRC m_pMotionBlurDofTechName;
	CCryNameTSCRC m_pMotionBlurDisplTechName;
	CCryNameTSCRC m_pMotionBlurRefTechName;

	CCryNameTSCRC m_pRefDofMBNormalize;

	CCryNameR m_pViewReprojParamName[4];
	CCryNameR m_pParamLensSamplesName[18];

	CCryNameR m_pDiretionalBlurParamName;
	CCryNameR m_pMotionBlurParamsName;
	CCryNameR m_pDofFocusParam0Name;		
	CCryNameR m_pDofFocusParam1Name;		
	CCryNameR m_pRadBlurParamName;		
	CCryNameR m_pViewProjPrevParam;
	CCryNameR m_pViewProjParam;
	CCryNameR m_pVSMotionBlurParams;

	CCryNameR m_pMotionBlurParamName;

  // bool, int, float, float, bool, texture, float, float, int, float, float
  CEffectParam *m_pType, *m_pAmount, *m_pUseMask, *m_pMaskTex, *m_pFocusRange; 
  CEffectParam *m_pCameraSphereScale, *m_pVectorsScale, *m_pUserVectorsScale, *m_pQuality, *m_pExposureTime, *m_pChromaShift; 
	CEffectParam *m_pRadBlurAmount, *m_pRadBlurScreenPosX, *m_pRadBlurScreenPosY, *m_pRadBlurRadius;    
	CEffectParam *m_pRadialBlurMaskTex, *m_pRadialBlurMaskUVScaleX, *m_pRadialBlurMaskUVScaleY;
	CEffectParam *m_pDrawNearZRangeOverride;
	CTexture *m_pBokehShape; 
      
	typedef std::map<uint32, SObjMotionBlurParams > OMBParamsMap;    
	typedef OMBParamsMap::iterator OMBParamsMapItor;
	static OMBParamsMap m_pOMBData[3]; // triple buffering: t0: being written, t-1: current render frame, t-2: previous render frame
	
	Matrix44A m_mScaleBias;
	
	IRenderMesh *m_pBokehQuadMesh;
	uint32 m_nBokehMeshWidth;
	uint32 m_nBokehMeshHeight;
	uint32 m_nBokehQuadTaps;
	
  float m_fPrevFrameTime;
  float m_fRotationAcc;
	
	float m_fRotSamplesEst;
	float m_fTransSamplesEst;
		
  int8 m_nSamplesInfo;
  
	bool m_bResetPrevScreen;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

struct SDepthOfFieldParams
{
	SDepthOfFieldParams():pMaskTex(0), fMaskBlendAmount(0.0f)
	{
	};

	Vec4 vFocus;
	Vec4 vMinZParams;
	bool bGameMode;

	CTexture *pMaskTex;
	float fMaskBlendAmount;
};

class CDepthOfField: public CPostEffect
{
public:
	CDepthOfField()
	{
		m_nRenderFlags = 0;
		m_nID = ePFX_eDepthOfField;

		// todo: add user values

		// Register technique and it's parameters
		AddParamBool("Dof_Active", m_pActive, 0);
		AddParamFloatNoTransition("Dof_FocusDistance", m_pFocusDistance, 3.5f);
		AddParamFloatNoTransition("Dof_FocusRange", m_pFocusRange, 0.0f);
		AddParamFloatNoTransition("Dof_FocusMin", m_pFocusMin, 2.0f);
		AddParamFloatNoTransition("Dof_FocusMax", m_pFocusMax, 10.0f);
		AddParamFloatNoTransition("Dof_FocusLimit", m_pFocusLimit, 100.0f);
		AddParamFloatNoTransition("Dof_MaxCoC", m_pMaxCoC, 12.0f);
		AddParamFloatNoTransition("Dof_CenterWeight", m_pCenterWeight, 1.0f);
		AddParamFloatNoTransition("Dof_BlurAmount", m_pBlurAmount, 1.0f);
		AddParamBool("Dof_UseMask", m_pUseMask, 0);
		AddParamTex("Dof_MaskTexName", m_pMaskTex, 0);      
		AddParamBool("Dof_Debug", m_pDebug, 0); 
		AddParamTex("Dof_BokehMaskName", m_pBokehMaskTex, 0);

		AddParamBool("Dof_User_Active", m_pUserActive, 0);
		AddParamFloatNoTransition("Dof_User_FocusDistance", m_pUserFocusDistance, 3.5f);
		AddParamFloatNoTransition("Dof_User_FocusRange", m_pUserFocusRange, 5.0f);
		AddParamFloatNoTransition("Dof_User_BlurAmount", m_pUserBlurAmount, 1.0f);

		AddParamFloatNoTransition("Dof_Tod_FocusRange", m_pTimeOfDayFocusRange, 1000.0f);
		AddParamFloatNoTransition("Dof_Tod_BlurAmount", m_pTimeOfDayBlurAmount, 0.0f);

		AddParamFloatNoTransition("Dof_FocusMinZ", m_pFocusMinZ, 0.0f); // 0.4 is good default
		AddParamFloatNoTransition("Dof_FocusMinZScale", m_pFocusMinZScale, 0.0f); // 1.0 is good default

		AddParamFloatNoTransition("FilterMaskedBlurring_Amount", m_pMaskedBlurAmount, 0.0f);
		AddParamTex("FilterMaskedBlurring_MaskTexName", m_pMaskedBlurMaskTex, 0);      

		m_fUserFocusRangeCurr = 0;
		m_fUserFocusDistanceCurr = 0;
		m_fUserBlurAmountCurr = 0;
		m_pNoise = 0;
		
		m_vBokehSamples.resize(8);
	}

  virtual int CreateResources();
  virtual void Release();
  virtual void Render();  
	void RenderHiQuality();
  void PoissonDofRender( const Vec4 &pFocusParams, const Vec4 &pBlurParams );
  void LayeredDofRender( const Vec4 &pFocusParams, const Vec4 &pBlurParams );
	
	SDepthOfFieldParams GetParams();

  virtual bool Preprocess();
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "DepthOfField";
  }

private:

  // bool, float, float, float, float
	CEffectParam *m_pUseMask, *m_pBokehMaskTex, *m_pFocusDistance, *m_pFocusRange, *m_pMaxCoC, *m_pCenterWeight, *m_pBlurAmount; 
  // float, float, float, CTexture, bool
  CEffectParam *m_pFocusMin, *m_pFocusMax, *m_pFocusLimit, *m_pMaskTex, *m_pDebug;
  // bool, float, float, float, float
  CEffectParam *m_pUserActive, *m_pUserFocusDistance, *m_pUserFocusRange, *m_pUserBlurAmount; 
  // float, float
  CEffectParam *m_pTimeOfDayFocusRange, *m_pTimeOfDayBlurAmount;
	// float, float
	CEffectParam *m_pFocusMinZ, *m_pFocusMinZScale;

	// float, CTexture
	CEffectParam *m_pMaskedBlurAmount, *m_pMaskedBlurMaskTex;    

  float m_fUserFocusRangeCurr;
  float m_fUserFocusDistanceCurr;
  float m_fUserBlurAmountCurr;
	
	std::vector< Vec4 > m_vBokehSamples;

  CTexture *m_pNoise;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CGlow: public CPostEffect
{
public:
	CGlow()
	{      
		m_nID = ePFX_eGlow;

		AddParamBool("Glow_Active", m_pActive, 0);
		AddParamFloat("Glow_Scale", m_pScale, 0.5f); // default glow scale (half strength)      

		AddParamVec4("clr_Glow_StreaksColor", m_pStreaksColor, Vec4(0.8f, 0.7f, 1.5f, 1.0f));
		AddParamFloat("Glow_StreaksMul", m_pStreaksMul, 3.0f);
		AddParamFloat("Glow_StreaksStretch", m_pStreaksStretch, 1.0f);
		AddParamFloat("Glow_FlaresMul", m_pFlaresMul, 0.25f);

		AddParamFloat("Glow_ScreenThreshold", m_pScreenThreshold, 0.5f);
		AddParamFloat("Glow_ScreenMul", m_pScreenMul, 0.2f);
	}


  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "Glow";
  }

private:

  CEffectParam *m_pScale;
  CEffectParam *m_pScreenThreshold, *m_pScreenMul;
  CEffectParam *m_pStreaksColor, *m_pStreaksMul, *m_pStreaksStretch, *m_pFlaresMul;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CSunShafts: public CPostEffect
{
public:
	CSunShafts()
	{      
		m_nID = ePFX_SunShafts;
		m_pOcclQuery = 0;

		AddParamBool("SunShafts_Active", m_pActive, 0);
		AddParamInt("SunShafts_Type", m_pShaftsType, 0); // default shafts type - highest quality
		AddParamFloatNoTransition("SunShafts_Amount", m_pShaftsAmount, 0.25f); // shafts visibility
		AddParamFloatNoTransition("SunShafts_RaysAmount", m_pRaysAmount, 0.25f); // rays visibility
		AddParamFloatNoTransition("SunShafts_RaysAttenuation", m_pRaysAttenuation, 5.0f); // rays attenuation
		AddParamFloatNoTransition("SunShafts_RaysSunColInfluence", m_pRaysSunColInfluence, 1.0f); // sun color influence    
		AddParamVec4NoTransition("SunShafts_RaysCustomColor", m_pRaysCustomCol, Vec4(1.0f, 1.0f, 1.0f, 1.0f));
		AddParamFloat("Scratches_Strength", m_pScratchStrength, 0.0f);
		AddParamFloat("Scratches_Threshold", m_pScratchThreshold, 0.0f);
		AddParamFloat("Scratches_Intensity", m_pScratchIntensity, 0.7f);
		m_bShaftsEnabled = false;
		m_nVisSampleCount = 0;
	}

  
  virtual int Initialize();
  virtual void Release();
  virtual void OnLostDevice();
  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

	bool SunShaftsGen( CTexture *pSunShafts, CTexture *pSunShaftsTemp );	
	void GetSunShaftsParams( Vec4 pParams[2] )
	{
		pParams[0] = m_pRaysCustomCol->GetParamVec4();
		pParams[1] = Vec4(0, 0, m_pRaysAmount->GetParam(), m_pRaysSunColInfluence->GetParam());
	}

  virtual const char *GetName() const
  {
    return "MergedSunShaftsEdgeAAColorCorrection";
  }

private:

  bool m_bShaftsEnabled;
  uint32 m_nVisSampleCount;

  // int, float, float, float, vec4
  CEffectParam *m_pShaftsType, *m_pShaftsAmount, *m_pRaysAmount, *m_pRaysAttenuation, *m_pRaysSunColInfluence, *m_pRaysCustomCol;
  CEffectParam *m_pScratchStrength, *m_pScratchThreshold, *m_pScratchIntensity;
  COcclusionQuery *m_pOcclQuery;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CFilterSharpening: public CPostEffect
{
public:
	CFilterSharpening()
	{
		m_nID = ePFX_FilterSharpening;

		AddParamInt("FilterSharpening_Type", m_pType, 0);
		AddParamFloat("FilterSharpening_Amount", m_pAmount, 1.0f);
	}
  
  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "FilterSharpening";
  }

private:

  // float, int
  CEffectParam *m_pAmount, *m_pType;    
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CFilterBlurring: public CPostEffect
{
public:
	CFilterBlurring()
	{     
		m_nID = ePFX_FilterBlurring;

		AddParamInt("FilterBlurring_Type", m_pType, 0);
		AddParamFloat("FilterBlurring_Amount", m_pAmount, 0.0f);
	}

  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "FilterBlurring";
  }

private:

  // float, int
  CEffectParam *m_pAmount, *m_pType;    
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CUberGamePostProcess: public CPostEffect
{
public:

	// Bitmaks used to enable only certain effects or combinations of most expensive effects
	enum EPostsProcessMask
	{
		ePE_SyncArtifacts = (1<<0),
		ePE_RadialBlur = (1<<1),
		ePE_ChromaShift = (1<<2),
	};

	CUberGamePostProcess()
	{     
		m_nID = ePFX_UberGamePostProcess;
		m_nCurrPostEffectsMask = 0;
		
		AddParamTex("tex_VisualArtifacts_Mask", m_pMask, 0);

		AddParamVec4("clr_VisualArtifacts_ColotTint", m_pColorTint, Vec4(1.0f, 1.0f, 1.0f, 1.0f));

		AddParamFloat("VisualArtifacts_Vsync", m_pVSyncAmount, 0.0f);
		AddParamFloat("VisualArtifacts_VsyncFreq", m_pVSyncFreq, 1.0f);

		AddParamFloat("VisualArtifacts_Interlacing", m_pInterlationAmount, 0.0f);
		AddParamFloat("VisualArtifacts_InterlacingTile", m_pInterlationTilling, 1.0f);
		AddParamFloat("VisualArtifacts_InterlacingRot", m_pInterlationRotation, 0.0f);

		AddParamFloat("VisualArtifacts_Pixelation", m_pPixelationScale, 0.0f);
		AddParamFloat("VisualArtifacts_Noise", m_pNoise, 0.0f);		
		
		AddParamFloat("VisualArtifacts_SyncWaveFreq", m_pSyncWaveFreq, 0.0f);
		AddParamFloat("VisualArtifacts_SyncWavePhase", m_pSyncWavePhase, 0.0f);
		AddParamFloat("VisualArtifacts_SyncWaveAmplitude", m_pSyncWaveAmplitude, 0.0f);
				
		AddParamFloat("FilterChromaShift_User_Amount", m_pFilterChromaShiftAmount, 0.0f); // Kept for backward - compatibility
		AddParamFloat("FilterArtifacts_ChromaShift", m_pChromaShiftAmount, 0.0f);		

		AddParamFloat("FilterGrain_Amount", m_pFilterGrainAmount, 0.0f);// Kept for backward - compatibility
		AddParamFloat("FilterArtifacts_Grain", m_pGrainAmount, 0.0f);
		AddParamFloatNoTransition("FilterArtifacts_GrainTile", m_pGrainTile, 1.0f);   
	}

  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "UberGamePostProcess";
  }

private:	
	CEffectParam *m_pVSyncAmount;
	CEffectParam *m_pVSyncFreq;

	CEffectParam *m_pColorTint;

	CEffectParam *m_pInterlationAmount;
	CEffectParam *m_pInterlationTilling;
	CEffectParam *m_pInterlationRotation;

	CEffectParam *m_pPixelationScale;
	CEffectParam *m_pNoise;

	CEffectParam *m_pSyncWaveFreq;
	CEffectParam *m_pSyncWavePhase;
	CEffectParam *m_pSyncWaveAmplitude;
	
	CEffectParam *m_pFilterChromaShiftAmount;
  CEffectParam *m_pChromaShiftAmount;
	
	CEffectParam *m_pGrainAmount;
	CEffectParam *m_pFilterGrainAmount; // todo: add support
	CEffectParam *m_pGrainTile;

	CEffectParam *m_pMask;

	uint8 m_nCurrPostEffectsMask;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CColorGrading: public CPostEffect
{
public:
	CColorGrading()
	{     
		m_nID = ePFX_ColorGrading;

		// levels adjustment
		AddParamFloatNoTransition("ColorGrading_minInput", m_pMinInput, 0.0f);
		AddParamFloatNoTransition("ColorGrading_gammaInput", m_pGammaInput, 1.0f);
		AddParamFloatNoTransition("ColorGrading_maxInput", m_pMaxInput, 255.0f);
		AddParamFloatNoTransition("ColorGrading_minOutput", m_pMinOutput, 0.0f);
		AddParamFloatNoTransition("ColorGrading_maxOutput", m_pMaxOutput, 255.0f);

		// generic color adjustment
		AddParamFloatNoTransition("ColorGrading_Brightness", m_pBrightness, 1.0f);
		AddParamFloatNoTransition("ColorGrading_Contrast", m_pContrast, 1.0f);
		AddParamFloatNoTransition("ColorGrading_Saturation", m_pSaturation, 1.0f);

		// filter color
		m_pDefaultPhotoFilterColor = Vec4( 0.952f, 0.517f, 0.09f, 1.0f );
		AddParamVec4NoTransition("clr_ColorGrading_PhotoFilterColor", m_pPhotoFilterColor,  m_pDefaultPhotoFilterColor);  // use photoshop default orange
		AddParamFloatNoTransition("ColorGrading_PhotoFilterColorDensity", m_pPhotoFilterColorDensity, 0.0f);

		// selective color
		AddParamVec4NoTransition("clr_ColorGrading_SelectiveColor", m_pSelectiveColor, Vec4(0.0f,0.0f,0.0f,0.0f)),
		AddParamFloatNoTransition("ColorGrading_SelectiveColorCyans", m_pSelectiveColorCyans, 0.0f),
		AddParamFloatNoTransition("ColorGrading_SelectiveColorMagentas", m_pSelectiveColorMagentas, 0.0f),
		AddParamFloatNoTransition("ColorGrading_SelectiveColorYellows", m_pSelectiveColorYellows, 0.0f),
		AddParamFloatNoTransition("ColorGrading_SelectiveColorBlacks", m_pSelectiveColorBlacks, 0.0f),

		// mist adjustment
		AddParamFloatNoTransition("ColorGrading_GrainAmount", m_pGrainAmount, 0.0f);
		AddParamFloatNoTransition("ColorGrading_SharpenAmount", m_pSharpenAmount, 1.0f);

		// user params
		AddParamFloatNoTransition("ColorGrading_Saturation_Offset", m_pSaturationOffset, 0.0f);
		AddParamVec4NoTransition("ColorGrading_PhotoFilterColor_Offset", m_pPhotoFilterColorOffset, Vec4(0.0f, 0.0f, 0.0f, 0.0f));
		AddParamFloatNoTransition("ColorGrading_PhotoFilterColorDensity_Offset", m_pPhotoFilterColorDensityOffset, 0.0f);
		AddParamFloatNoTransition("ColorGrading_GrainAmount_Offset", m_pGrainAmountOffset, 0.0f);
	}

  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);
	bool UpdateParams( SColorGradingMergeParams &pMergeParams );

  virtual const char *GetName() const
  {
    return "ColorGrading";
  }

private:

  // levels adjustment
  CEffectParam *m_pMinInput;
  CEffectParam *m_pGammaInput;
  CEffectParam *m_pMaxInput;
  CEffectParam *m_pMinOutput;
  CEffectParam *m_pMaxOutput;

  // generic color adjustment
  CEffectParam *m_pBrightness;
  CEffectParam *m_pContrast;
  CEffectParam *m_pSaturation;
  CEffectParam *m_pSaturationOffset;

  // filter color
  CEffectParam *m_pPhotoFilterColor;
  CEffectParam *m_pPhotoFilterColorDensity;
  CEffectParam *m_pPhotoFilterColorOffset;
  CEffectParam *m_pPhotoFilterColorDensityOffset;
  Vec4 m_pDefaultPhotoFilterColor;

  // selective color
  CEffectParam *m_pSelectiveColor;
  CEffectParam *m_pSelectiveColorCyans;
  CEffectParam *m_pSelectiveColorMagentas;
  CEffectParam *m_pSelectiveColorYellows;
  CEffectParam *m_pSelectiveColorBlacks;

  // misc adjustments
  CEffectParam *m_pGrainAmount;
  CEffectParam *m_pGrainAmountOffset;

  CEffectParam *m_pSharpenAmount;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CUnderwaterGodRays: public CPostEffect
{
public:
	CUnderwaterGodRays()
	{     
		m_nID = ePFX_eUnderwaterGodRays;

		AddParamFloat("UnderwaterGodRays_Amount", m_pAmount, 1.0f);
		AddParamInt("UnderwaterGodRays_Quality", m_pQuality, 1); // 0 = low, 1 = med, 2= high, 3= ultra-high, 4= crazy high, and so on

	}

  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "UnderwaterGodRays";
  }

private:

  // float, int
  CEffectParam *m_pAmount, *m_pQuality;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CVolumetricScattering: public CPostEffect
{
public:
	CVolumetricScattering()
	{     
		m_nID = ePFX_eVolumetricScattering;

		AddParamFloat("VolumetricScattering_Amount", m_pAmount, 0.0f);
		AddParamFloat("VolumetricScattering_Tilling", m_pTilling, 1.0f);
		AddParamFloat("VolumetricScattering_Speed", m_pSpeed, 1.0f);
		AddParamVec4("clr_VolumetricScattering_Color", m_pColor, Vec4( 0.5f, 0.75f, 1.0f, 1.0f ) );    

		AddParamInt("VolumetricScattering_Type", m_pType, 0); // 0 = alien environment, 1 = ?, 2 = ?? ???
		AddParamInt("VolumetricScattering_Quality", m_pQuality, 1); // 0 = low, 1 = med, 2= high, 3= ultra-high, 4= crazy high, and so on    
	}

  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "VolumetricScattering";
  }

private:

  // float, int, int
  CEffectParam *m_pAmount, *m_pTilling, *m_pSpeed, *m_pColor, *m_pType, *m_pQuality;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Game/Hud specific post-effects
////////////////////////////////////////////////////////////////////////////////////////////////////

class CAlienInterference: public CPostEffect
{
public:
	CAlienInterference()
	{     
		m_nID = ePFX_eAlienInterference;

		AddParamFloat("AlienInterference_Amount", m_pAmount, 0);
		AddParamVec4NoTransition("clr_AlienInterference_Color", m_pTintColor, Vec4(Vec3(0.85f, 0.95f, 1.25f)*0.5f, 1.0f));
	}

  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "AlienInterference";
  }

private:

  // float
  CEffectParam *m_pAmount; 
	// vec4
	CEffectParam *m_pTintColor;

};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CWaterDroplets: public CPostEffect
{
public:
	CWaterDroplets()
	{     
		m_nID = ePFX_eWaterDroplets;

		AddParamFloat("WaterDroplets_Amount", m_pAmount, 0.0f);

		m_fLastSpawnTime = 0.0f;
		m_fCurrLifeTime = 1000.0f;
		m_bWasUnderWater = true;
	}

  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "WaterDroplets";
  }

private:

  bool m_bWasUnderWater;
  float m_fLastSpawnTime;
  float m_fCurrLifeTime;

  // float
  CEffectParam *m_pAmount;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CWaterFlow: public CPostEffect
{
public:
	CWaterFlow()
	{     
		m_nID = ePFX_eWaterFlow;

		AddParamFloat("WaterFlow_Amount", m_pAmount, 0.0f);
	}

  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "WaterFlow";
  }

private:

  // float
  CEffectParam *m_pAmount;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CWaterRipples: public CPostEffect
{
public:
	CWaterRipples(): m_bPhysCallbackInitialized(false), m_bSnapToCenter(false), m_bInitializeSim(true)
	{       
		m_nRenderFlags = 0;
		m_nID = ePFX_WaterRipples;

		AddParamFloatNoTransition("WaterRipples_Amount", m_pAmount, 0.0f);

		m_pRipplesGenTechName = "WaterRipplesGen";
		m_pRipplesHitTechName = "WaterRipplesHit";
		m_pRipplesParamName = "WaterRipplesParams";

		m_fLastSpawnTime = 0.0f;
		m_fSimGridSize = 20.0f;
		m_fSimGridSizeRcp = 1.0f / m_fSimGridSize;
		m_fSimGridSnapRange = 5.0f;

		m_vLastSnapPos = Vec2(ZERO);	

		s_nUpdateMask = 0;
	}

  virtual bool Preprocess();

	// Enabled/Disabled if no hits on list to process - call from render thread
	bool RT_SimulationStatus();

	// Add hits to list - called from main thread
	static void AddHit(const Vec3 &vPos);

	virtual void Release()
	{
		Reset();
	}

	void RenderHits();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "WaterRipples";
  }
	
private:

	static int OnEventPhysArea(const struct EventPhys *pEvent);

private:

	CCryNameTSCRC m_pRipplesGenTechName;
	CCryNameTSCRC m_pRipplesHitTechName;
	CCryNameR m_pRipplesParamName;

  // float
  CEffectParam *m_pAmount;
  float m_fLastSpawnTime;

	float m_fSimGridSize;
	float m_fSimGridSizeRcp;
	float m_fSimGridSnapRange;

	Vec2 m_vLastSnapPos;
	static std::vector< Vec2 > s_pWaterHits[RT_COMMAND_BUF_COUNT];
  static std::vector< Vec2 > s_pWaterHitsMGPU;
  static Vec3 s_CameraPos;
  static int s_nUpdateMask;
  static Vec4 s_vParams;
  static bool s_bInitializeSim;

	bool m_bPhysCallbackInitialized;
	bool m_bSnapToCenter;
	bool m_bInitializeSim;

};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CWaterVolume: public CPostEffect
{
public:
	CWaterVolume()
	{        
		m_nRenderFlags = 0;
		m_nID = ePFX_WaterVolume;

		AddParamFloatNoTransition("WaterVolume_Amount", m_pAmount, 0.0f);
		m_nCurrSimID = 0;
	}

  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);
  int GetCurrentPuddle() 
  {
    return m_nCurrSimID;
  }

  virtual const char *GetName() const
  {
    return "WaterVolume";
  }

private:

  // float
  CEffectParam *m_pAmount;
  int m_nCurrSimID;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CScreenFrost: public CPostEffect
{
public:
	CScreenFrost()
	{ 
		m_nID = ePFX_eScreenFrost;

		AddParamFloat("ScreenFrost_Amount", m_pAmount, 0.0f); // amount of visible frost
		AddParamFloat("ScreenFrost_CenterAmount", m_pCenterAmount, 1.0f); // amount of visible frost in center

		m_fRandOffset = 0;
	}

  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "ScreenFrost";
  }

private:

  // float, float
  CEffectParam *m_pAmount, *m_pCenterAmount;
  float m_fRandOffset;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CRainDrops: public CPostEffect
{
public:
	CRainDrops()
	{     
		m_nID = ePFX_eRainDrops;

		AddParamFloat("RainDrops_Amount", m_pAmount, 0.0f); // amount of visible droplets
		AddParamFloat("RainDrops_SpawnTimeDistance", m_pSpawnTimeDistance, 0.35f); // amount of visible droplets
		AddParamFloat("RainDrops_Size", m_pSize, 5.0f); // drop size
		AddParamFloat("RainDrops_SizeVariation", m_pSizeVar, 2.5f); // drop size variation

		AddParamFloat("DISABLED_Moisture_Amount", m_pMoistureAmount, 0.0f);		// amount of overall visible moisture
		AddParamFloat("Moisture_Hardness", m_pMoistureHardness, 10.0f);	// hardness of blending		
		AddParamFloat("Moisture_DropletAmount", m_pMoistureDropletAmount, 7.0f);	//factor applied to droplets map
		AddParamFloat("Moisture_Variation", m_pMoistureVariation, 0.2f); //factor to random
		AddParamFloat("Moisture_Speed", m_pMoistureSpeed, 1.0f);			//animation speed
		AddParamFloat("Moisture_FogAmount", m_pMoistureFogAmount, 1.0f);	//amount of fog
				
		m_uCurrentDytex = 0;

		m_ptexMoisture	= 0;
		m_ptexNoise		= 0;

		m_pVelocityProj = Vec3(0,0,0);
				

		m_nAliveDrops = 0;

		m_pPrevView.SetIdentity();    
		m_pViewProjPrev.SetIdentity();

		m_bMoisture = false;
		m_vMoistureNoiseOffsets = Vec4(0,0,0,0);
		m_vMoistureDropsOffsets = Vec4(0,0,0,0);
		m_vMoistureRandom		= Vec4(0,0,0,0);
		m_vMoistureDropsFactors	= Vec4(0,0,0,0);

		m_fMoistureStrength = 0.0f;
		m_fMoistureCoverage = 0.0f;
		m_fMoistureFogCoverage = 0.0f;
		m_fMoistureFade		= 1.0f;

		m_bFirstFrame = true;
	}

	virtual ~CRainDrops()
	{
		Release();
	}

  virtual int CreateResources();
  virtual bool Preprocess();
  virtual void Render();
  virtual void Reset(bool bOnSpecChange = false);
  virtual void Release();

  virtual const char *GetName() const;

private:

  // Rain particle properties
  struct SRainDrop  
  {      
    // set default data
    SRainDrop(): m_pPos(0,0,0), m_fSize(5.0f), m_fSizeVar(2.5f), m_fSpawnTime(0.0f), m_fLifeTime(2.0f), m_fLifeTimeVar(1.0f),
      m_fWeight(1.0f), m_fWeightVar(0.25f)
    {

    }

    // Screen position
    Vec3 m_pPos;               
    // Size and variation (bigger also means more weight)
    float m_fSize, m_fSizeVar; 
    // Spawn time
    float m_fSpawnTime;                
    // Life time and variation
    float m_fLifeTime, m_fLifeTimeVar; 
    // Weight and variation
    float m_fWeight, m_fWeightVar; 
  };

  //in Preprocess(), check if effect is active
  bool IsActiveMoisture();
  bool IsActiveRain();

  // Compute current interpolated view matrix
  Matrix44 ComputeCurrentView( int iViewportWidth, int iViewportHeight );

  // Spawn a particle
  void SpawnParticle( SRainDrop *&pParticle, int iRTWidth, int iRTHeight );   
  // Update all particles
  void UpdateParticles( int iRTWidth, int iRTHeight );
  // Generate rain drops map
  void RainDropsMapGen();
  // Draw the raindrops
  void DrawRaindrops( int iViewportWidth, int iViewportHeight, int iRTWidth, int iRTHeight );
  // Apply the blur and movement to it
  void ApplyExtinction( CTexture*& rptexPrevRT, int iViewportWidth, int iViewportHeight, int iRTWidth, int iRTHeight );

  // Update moisture droplets
  void UpdateMoisture();
  // Draw moisture/or fill RT bacbuffer with prev frame
  void DrawMoisture( int iRTWidth, int iRTHeight );

  // Final draw pass, merge with backbuffer
  void DrawFinal(CTexture*& rptexCurrRT);

  // float
  CEffectParam *m_pAmount;
  CEffectParam *m_pSpawnTimeDistance;
  CEffectParam *m_pSize;
  CEffectParam *m_pSizeVar;  

  CEffectParam *m_pMoistureAmount;			//overall moisture amount
  CEffectParam *m_pMoistureHardness;		//moisture blend softness  
  CEffectParam *m_pMoistureDropletAmount;	//moisture droplet amount
  CEffectParam *m_pMoistureVariation;		//factor to random
  CEffectParam *m_pMoistureSpeed;			//animation speed
  CEffectParam *m_pMoistureFogAmount;		//moisture fog amount
    
  bool	m_bMoisture;
  float m_fMoistureFade;

  Vec4	m_vMoistureNoiseOffsets;
  Vec4	m_vMoistureRandom;

  Vec4	m_vMoistureDropsOffsets;
  Vec4	m_vMoistureDropsFactors;

  float m_fMoistureCoverage;
  float m_fMoistureStrength;
  float m_fMoistureFogCoverage;
  
  uint16		m_uCurrentDytex;
  bool			m_bFirstFrame;

  CTexture*		m_ptexMoisture;
  CTexture*		m_ptexNoise;

  //todo: use generic screen particles
  typedef std::vector<SRainDrop*> SRainDropsVec;
  typedef SRainDropsVec::iterator SRainDropsItor;
  SRainDropsVec m_pDropsLst;    

  Vec3 m_pVelocityProj;
  Matrix44 m_pPrevView;    
  Matrix44 m_pViewProjPrev;

  int m_nAliveDrops;
  static const int m_nMaxDropsCount = 100;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CNightVision: public CPostEffect
{
public:
	CNightVision()
	{     
		m_nID = ePFX_NightVision;

		AddParamBool("NightVision_Active", m_pActive, 0);
		AddParamFloat("NightVision_BlindAmount", m_pAmount, 0.0f);

		m_bWasActive = false;
		m_fRandOffset = 0;    
		m_fPrevEyeAdaptionBase = 0.25f;
		m_fPrevEyeAdaptionSpeed = 100.0f;

		m_pGradient = 0;
		m_pNoise = 0;
		m_fActiveTime = 0.0f;
	}

  virtual int CreateResources();
  virtual void Release();
  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "NightVision";
  }

private:
  // float
  CEffectParam *m_pAmount;

  bool m_bWasActive;
  float m_fActiveTime;

  float m_fRandOffset;
  float m_fPrevEyeAdaptionSpeed;
  float m_fPrevEyeAdaptionBase;

  CTexture *m_pGradient;
  CTexture *m_pNoise;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CSonarVision: public CPostEffect
{
public:
	CSonarVision()
	{     
		m_nID = ePFX_SonarVision;

		AddParamBool("SonarVision_Active", m_pActive, 0);
		AddParamFloat("SonarVision_Amount", m_pAmount, 0.0f);

		m_pGradient = 0;
		m_pNoise = 0;

		m_pszAmbientTechName = "SonarVisionAmbient"; 	
		m_pszSoundHintsTechName = "SonarVisionSoundHint";
		m_pszTechFinalComposition = "SonarVisionFinalComposition";
		m_pszTechNameGhosting = "SonarVisionGhosting"; 
		m_pszParamNameVS = "SonarVisionParamsVS";
		m_pszParamNamePS = "SonarVisionParamsPS";

		m_pSoundEventsListener = NULL;
	}

	virtual int CreateResources();
	virtual void Release();
	virtual bool Preprocess();
	virtual void Render();  
	virtual void Reset(bool bOnSpecChange = false);
	
	void UpdateSoundEvents();
	
	void AmbientPass();
	void SoundHintsPass();
	void GhostingPass();
	void FinalComposePass();

	virtual const char *GetName() const
	{
		return "SonarVision";
	}

private:
	
	CSoundEventsListener *m_pSoundEventsListener;

	CEffectParam *m_pAmount;
	CTexture *m_pGradient;
	CTexture *m_pNoise;

	CCryNameTSCRC m_pszAmbientTechName; 
	CCryNameTSCRC m_pszSoundHintsTechName;
	CCryNameTSCRC m_pszTechFinalComposition;
	CCryNameTSCRC m_pszTechNameGhosting; 
	CCryNameR m_pszParamNameVS;
	CCryNameR m_pszParamNamePS;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CThermalVision: public CPostEffect
{
public:
	CThermalVision()
	{     
		m_nRenderFlags = 0; // thermal vision replaces "rendering" , no need to update
		m_nID = ePFX_ThermalVision;

		AddParamBool("ThermalVision_Active", m_pActive, 0);
		AddParamFloat("ThermalVision_Amount", m_pAmount, 0.0f);
		AddParamFloat("ThermalVision_CamMovNoiseAmount", m_pCamMovNoiseAmount, 0.0f);

		m_pGradient = 0;
		m_pNoise = 0;

		m_pszAmbientTechName = "ThermalVisionAmbient"; 
		m_pszTechFinalComposition = "ThermalVisionComposition"; 
		m_pszTechNameGhosting = "ThermalVisionGhosting"; 
		m_pszParamNameVS = "ThermalVisionParamsVS";
		m_pszParamNamePS = "ThermalVisionParamsPS";
		m_fBlending = m_fCameraMovementAmount = 0.0f;

		m_bInit = true;
	}

	virtual int CreateResources();
	virtual void Release();
	virtual bool Preprocess();
	virtual void Render();  
	virtual void Reset(bool bOnSpecChange = false);

	void AmbientPass();
	void HeatSourcesPasses();
	void GhostingPass();
	void FinalComposePass();

	bool GetTransitionEffectState()
	{
		if( m_fBlending < 0.01f )
			return true;

		return false;
	}

	// Get sonar params: position/radius/lifetime/color multiplier
	void GetSonarParams(Vec4 pParams[3])
	{
		pParams[0] = Vec4( m_pSonarParams[0].vPosition, m_pSonarParams[0].fRadius );
		pParams[1] = Vec4( m_pSonarParams[1].vPosition, m_pSonarParams[1].fRadius );
		pParams[2] = Vec4( m_pSonarParams[0].fCurrLifetime/(m_pSonarParams[0].fLifetime+1e-6f), 
											 m_pSonarParams[0].fColorMul,
											 m_pSonarParams[1].fCurrLifetime/(m_pSonarParams[1].fLifetime+1e-6f), 
											 m_pSonarParams[1].fColorMul );		
	}

	virtual const char *GetName() const
	{
		return "ThermalVision";
	}

private:

	CEffectParam *m_pAmount, *m_pCamMovNoiseAmount;
	CTexture *m_pGradient;
	CTexture *m_pNoise;
	bool m_bInit;

	struct SSonarParams
	{
		Vec3 vPosition;
		float fRadius;
		float fLifetime;
		float fCurrLifetime;
		float fColorMul;
	};

	SSonarParams m_pSonarParams[2];
	
	float m_fBlending;
	float m_fCameraMovementAmount;

	CCryNameTSCRC m_pszAmbientTechName; 
	CCryNameTSCRC m_pszTechFinalComposition;
	CCryNameTSCRC m_pszTechNameGhosting; 
	CCryNameR m_pszParamNameVS;
	CCryNameR m_pszParamNamePS;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CHudSilhouettes: public CPostEffect
{
public:
	CHudSilhouettes()
	{        
		m_nRenderFlags = 0;
		m_nID = ePFX_HUDSilhouettes;

		AddParamBool("HudSilhouettes_Active", m_pActive, 0);
		AddParamFloatNoTransition("HudSilhouettes_Amount", m_pAmount, 1.0f); //0.0f gives funky blending result ? investigate
		AddParamInt("HudSilhouettes_Type", m_pType, 1);
	}

  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "HUDSilhouettes";
  }

private:

  // float
  CEffectParam *m_pAmount, *m_pType;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CFlashBang: public CPostEffect
{
public:
	CFlashBang()
	{     			
		m_nID = ePFX_eFlashBang;

		AddParamBool("FlashBang_Active", m_pActive, 0);     
		AddParamFloat("FlashBang_DifractionAmount", m_pDifractionAmount, 1.0f);     
		AddParamFloat("FlashBang_Time", m_pTime, 2.0f); // flashbang time duration in seconds 
		AddParamFloat("FlashBang_BlindAmount", m_pBlindAmount, 0.5f); // flashbang blind time (fraction of frashbang time)

		m_pGhostImage = 0;
		m_fBlindAmount = 1.0f;
		m_fSpawnTime = 0.0f;
	}

	virtual ~CFlashBang()
	{
		Release();
	}

  virtual bool Preprocess();
  virtual void Release();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "FlashBang";
  }

private:

  SDynTexture *m_pGhostImage;

  float m_fBlindAmount;
  float m_fSpawnTime;

  // float, float
  CEffectParam *m_pTime, *m_pDifractionAmount, *m_pBlindAmount;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CGammaReference: public CPostEffect
{
public:
	CGammaReference()
	{
		m_nRenderFlags = 0;
		m_nID = ePFX_GammaReference;
		m_pGammaReference = 0;

		AddParamBool("GammaReference_Active", m_pActive, 1);
	}

  virtual bool Preprocess();
  virtual void Render();  
  virtual void Reset(bool bOnSpecChange = false);

  virtual const char *GetName() const
  {
    return "GammaReference";
  }

private:

  CTexture *m_pGammaReference;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CSceneRain: public CPostEffect
{
public:
	CSceneRain()
	{     
		m_nRenderFlags = 0;
		m_nID = ePFX_SceneRain;

		m_pConeVB = 0;
		m_nConeVBSize = 0;
		m_bReinit = true;

		AddParamBool("SceneRain_Active", m_pActive, 0);
	}

	virtual int CreateResources();
	virtual void Release();
	virtual bool Preprocess();
	virtual void Render();  
	virtual void Reset(bool bOnSpecChange = false);
	virtual void OnLostDevice();

	virtual const char *GetName() const;

	// Rain volume parameters (filled during rain layer/occ generation pass)
	N3DEngineCommon::SRainInfo m_RainVolParams;

private:
	bool m_bReinit;
	void * m_pConeVB;
	uint16 m_nConeVBSize;
	void CreateBuffers(uint16 nVerts, void * &pINVB, SVF_P3F_C4B_T2F * pVtxList);
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CSceneSnow: public CPostEffect
{
public:
	CSceneSnow()
	{     
		m_nID = ePFX_SceneSnow;

		AddParamBool("SceneSnow_Active", m_pActive, 0);
			
		m_nAliveClusters = 0;
		m_pSnowFlakeMesh = NULL;
	}

	virtual ~CSceneSnow()
	{
		Release();
	}

	bool IsActiveSnow();

  virtual int CreateResources();
  virtual bool Preprocess();
  virtual void Render();
  virtual void Reset(bool bOnSpecChange = false);
  virtual void Release();

  virtual const char *GetName() const;

  // Rain volume parameters (filled during rain layer/occ generation pass)
  // Needed for occlusion.
  N3DEngineCommon::SRainInfo m_RainVolParams;
  N3DEngineCommon::SSnowInfo m_SnowVolParams;

private:

  // Snow particle properties
  struct SSnowCluster  
  {      
    // set default data
    SSnowCluster(): m_pPos(0,0,0), m_pPosPrev(0,0,0), m_fSpawnTime(0.0f), m_fLifeTime(4.0f), m_fLifeTimeVar(2.5f), m_fWeight(0.3f), m_fWeightVar(0.1f)
    {

	}
	
	// World position
    Vec3 m_pPos, m_pPosPrev;
    // Spawn time
    float m_fSpawnTime;
    // Life time and variation
    float m_fLifeTime, m_fLifeTimeVar;
	// Weight and variation
	float m_fWeight, m_fWeightVar;
  };

  // Generate particle cluster mesh
  bool GenerateClusterMesh();
  // Spawn a cluster
  void SpawnCluster( SSnowCluster *&pCluster );   
  // Update all clusters
  void UpdateClusters();
  // Draw clusters
  void DrawClusters();
  // Half resolution composite.
  void HalfResComposite();

  // float
  CEffectParam *m_pActive;

  typedef std::vector<SSnowCluster*> SSnowClusterVec;
  typedef SSnowClusterVec::iterator SSnowClusterItor;
  SSnowClusterVec m_pClusterList;    

  IRenderMesh *m_pSnowFlakeMesh;
  int m_nSnowFlakeVertCount;

  int m_nAliveClusters;
  int m_nNumClusters;
  int m_nFlakesPerCluster;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CPostAA: public CPostEffect
{
public:
	CPostAA()
	{		    
		m_nRenderFlags = 0;
		m_nID = ePFX_PostAA;
		m_pPrevView.SetIdentity();
		m_pPrevViewProj[0].SetIdentity();
		m_pPrevViewProj[1].SetIdentity();

		m_pAreaSMAA = 0; 
		m_pSearchSMAA = 0;

		m_bInit = true;
		m_nScopeZoomTransition = 0;
		AddParamBool("PostAA_Scope", m_pScopeZoom, 0);
	}

	virtual int CreateResources();
  virtual void Release();	
	virtual bool Preprocess();
	virtual void Render();  
	virtual void Reset(bool bOnSpecChange = false);

	Matrix44 GetPrevViewProj()
	{
		Matrix44A mViewProjPrev = m_pPrevViewProj[0];                  
		mViewProjPrev.Transpose();
		Matrix44A mScaleBias = Matrix44A(	0.5f,     0,	 0,   0,
			0,	-0.5f,   0,   0,
			0,		  0,	 1.0f,   0,						
			0.5f ,	 0.5f,   0,   1.0f);
		mViewProjPrev = mViewProjPrev * mScaleBias;
		mViewProjPrev.Transpose();

		return mViewProjPrev;
	}

	virtual const char *GetName() const
	{
		return "PostAA";
	}

private:

	Matrix44 m_pPrevView;    
	Matrix44 m_pPrevViewProj[2];    

	bool m_bInit;

	CTexture *m_pAreaSMAA; 	
	CTexture *m_pSearchSMAA;

	// Flags for iron scope zoom transition
	int8 m_nScopeZoomTransition;
	CEffectParam *m_pScopeZoom;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CSoftAlphaTest: public CPostEffect
{
public:
	CSoftAlphaTest()
	{		    
		m_nID = ePFX_eSoftAlphaTest;
	}

	virtual bool Preprocess();
	virtual void Render();  
	virtual void Reset(bool bOnSpecChange = false);
	virtual const char *GetName() const
	{
		return "SoftAlphaTest";
	}

private:
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CPostStereo: public CPostEffect
{
public:
	CPostStereo()
	{		    
		//		m_nRenderFlags = 0;
		m_nID = ePFX_PostStereo;
	}

	virtual bool Preprocess();
	virtual void Render();  
	virtual void Reset(bool bOnSpecChange = false);
	virtual const char *GetName() const
	{
		return "PostStereo";
	}
private:

};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CImageGhosting: public CPostEffect
{
public:
	CImageGhosting()
	{		    
		m_nRenderFlags = 0;
		m_nID = ePFX_ImageGhosting;
		AddParamFloat("ImageGhosting_Amount", m_pAmount, 0);
		m_bInit = true;
	}

	virtual bool Preprocess();
	virtual void Render();  
	virtual void Reset(bool bOnSpecChange = false);
	virtual const char *GetName() const
	{
		return "ImageGhosting";
	}

private:

	CEffectParam *m_pAmount;
	bool m_bInit;
};


////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
struct IUIElement;
class C3DHud: public CPostEffect
{
public:

	struct SHudData
	{
	public:
		SHudData(): pRE(0), pShaderItem(0), pShaderResources(0), pRO(0), pDiffuse(0), pFlashPlayer(0), nSortVal(0), nFlashWidth(0), nFlashHeight(0), bVisible(false)
		{
		}

		SHudData(const SHudData& o)
			: pRE(o.pRE)
			, pShaderItem(o.pShaderItem)
			, pShaderResources(o.pShaderResources)
			, pRO(o.pRO)
			, pFlashPlayer(0)
		{
			Init();
		}

		SHudData& operator= (const SHudData& o)
		{
			if( this == &o ) return *this;
			pRE = o.pRE;
			pShaderItem = o.pShaderItem;
			pShaderResources = o.pShaderResources;
			pRO = o.pRO;
			Init();
			return *this;
		}

		SHudData( const CRendElementBase *pInRE, const SShaderItem *pInShaderItem, const SRenderShaderResources *pInShaderResources, CRenderObject *pInRO):	
		pRE(pInRE), 						
			pShaderItem(pInShaderItem),
			pShaderResources(pInShaderResources),
			pRO(pInRO),
			pFlashPlayer(NULL)
		{
			Init();
		}

		~SHudData()
		{
			Release();
		}

	public:
		const CRendElementBase *pRE;
		CRenderObject *pRO;
		const SShaderItem *pShaderItem; // to be removed after Alpha MS
		const SRenderShaderResources *pShaderResources;

		SEfResTexture *pDiffuse;
		IFlashPlayer	*pFlashPlayer;

		uint32 nSortVal;				

		int16 nFlashWidth;
		int16 nFlashHeight;
		bool bVisible;

		static int16 s_nFlashWidthMax;
		static int16 s_nFlashHeightMax;

	private:
		void Init();
		void Release();
	};

	struct HudDataSortCmp
	{
		bool operator()(const SHudData& h0, const SHudData& h1) const
		{
			return h0.nSortVal > h1.nSortVal;
		}
	};

	typedef std::vector< SHudData > SHudDataVec;
	typedef std::vector< SHudData >::iterator SHudDataVecIt;

public:

	C3DHud()
	{		    
		m_nRenderFlags = PSP_REQUIRES_UPDATE;
		m_nID = ePFX_3DHUD;

		m_pHUD_RT = 0; 
		m_pHUDScaled_RT = 0;
		m_pNoise = 0;

		m_mViewProj.SetIdentity();

		AddParamFloatNoTransition("HUD3D_OpacityMultiplier", m_pOpacityMul, 1.0f);
		AddParamFloatNoTransition("HUD3D_GlowMultiplier", m_pGlowMul, 1.0f);
		AddParamFloatNoTransition("HUD3D_ChromaShift", m_pChromaShift, 0.0f);
		AddParamFloatNoTransition("HUD3D_DofMultiplier", m_pDofMultiplier, 1.0f);
		AddParamVec4NoTransition("clr_HUD3D_Color", m_pHudColor, Vec4(1.0f, 1.0f, 1.0f, 1.0f));

		AddParamFloat("HUD3D_FOV", m_pFOV, 55.0f);

		AddParamFloat("HUD3D_Interference", m_pInterference, 0.0f);

		// x= hudItemOverrideStrength, y= interferenceRandFrequency, z= dofInterferenceStrength, w = free
		AddParamVec4("HUD3D_InterferenceParams0", m_pInterferenceParams[0], Vec4(1.0f, 0.055f, 0.8f, 0.0f));

		// x = randomGrainStrengthScale, y= randomFadeStrengthScale, z= chromaShiftStrength, w= chromaShiftDist
		AddParamVec4("HUD3D_InterferenceParams1", m_pInterferenceParams[1], Vec4(0.3f, 0.4f, 0.25f, 1.0f));

		// x= disruptScale, y= disruptMovementScale, z= noiseStrength, w = barScale
		AddParamVec4("HUD3D_InterferenceParams2", m_pInterferenceParams[2], Vec4(0.3f, 1.0f, 0.2f, 0.8f));

		// xyz= barColor, w= barColorMultiplier
		AddParamVec4("HUD3D_InterferenceParams3", m_pInterferenceParams[3], Vec4(0.39f, 0.6f, 1.0f, 5.0f));

		AddParamBool("HUD3D_OverrideCacheDelay", m_pOverideCacheDelay, 0.0f);

		m_pGeneralTechName = "General";
		m_pDownsampleTechName = "Downsample4x4";
		m_pUpdateBloomTechName = "UpdateBloomRT";
		m_pHudParamName = "HudParams";
		m_pHudEffectsParamName = "HudEffectParams";
		m_pMatViewProjParamName = "mViewProj";
		m_pHudTexCoordParamName = "HudTexCoordParams";

		m_nFlashUpdateFrameID = -1;

		m_maxParallax = 0.0f;
		m_interferenceRandTimer = 0.0f;

		m_interferenceRandNums = Vec4(0.0f,0.0f,0.0f,0.0f);

#ifndef _RELEASE
		m_pTexToTexTechName = "TextureToTexture";
		m_bDebugView = false;
		m_bWireframeEnabled = false;
#endif
	}

	virtual int CreateResources();
	virtual void Release();
	virtual bool Preprocess();

	virtual void Update()
	{
		const uint32 nThreadID = gRenDev->m_RP.m_nProcessThreadID;
		if( !m_pRenderData[nThreadID].empty() )    
			std::sort(m_pRenderData[nThreadID].begin(), m_pRenderData[nThreadID].end(), HudDataSortCmp());
	}

	virtual void OnBeginFrame()
	{
		const uint32 nThreadID = gRenDev->m_RP.m_nFillThreadID;
		if( SRendItem::m_RecurseLevel[nThreadID] == 0 ) 
			m_pRenderData[nThreadID].resize(0);
	}

	virtual void Reset(bool bOnSpecChange = false);
	virtual void AddRE( const CRendElementBase *re, const SShaderItem *pShaderItem, CRenderObject *pObj);	
	virtual void Render();  

	// Shared shader params/textures setup
	void CalculateProjMatrix();
	void SetShaderParams( SHudData &pData );  
	void SetTextures( SHudData &pData );  
	void RenderMesh( const CRendElementBase *pRE, SShaderPass *pPass);

	void FlashUpdateRT();  
	void DownsampleHud4x4( CTexture *pDstRT );	
	void UpdateBloomRT( CTexture *pDstRT );
	void FinalPass();  
	void RenderFinalPass();

	virtual const char *GetName() const
	{
		return "3DHud";
	}

	CEffectParam* GetFov() const
	{
		return m_pFOV;
	}

private:

	Vec4 m_interferenceRandNums;
	float m_interferenceRandTimer;

	// Vec4, float
	CEffectParam *m_pOpacityMul;
	CEffectParam *m_pGlowMul;
	CEffectParam *m_pChromaShift;
	CEffectParam *m_pHudColor;
	CEffectParam *m_pDofMultiplier;
	CEffectParam* m_pFOV;
	CEffectParam* m_pInterference;
	CEffectParam* m_pInterferenceParams[4];
	CEffectParam* m_pOverideCacheDelay;
	CTexture *m_pHUD_RT;
	CTexture *m_pHUDScaled_RT;
	CTexture *m_pNoise;

	SHudDataVec m_pRenderData[RT_COMMAND_BUF_COUNT];

	Matrix44A m_mViewProj;

	CCryNameTSCRC m_pGeneralTechName;
	CCryNameTSCRC m_pDownsampleTechName;
	CCryNameTSCRC m_pUpdateBloomTechName;
	CCryNameR m_pHudParamName;
	CCryNameR m_pHudEffectsParamName;	
	CCryNameR m_pMatViewProjParamName;
	CCryNameR m_pHudTexCoordParamName;

	float m_maxParallax;
	int32 m_nFlashUpdateFrameID;

#ifndef _RELEASE
	CCryNameTSCRC m_pTexToTexTechName;
	bool m_bDebugView;
	bool m_bWireframeEnabled;
#endif
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CFilterKillCamera: public CPostEffect
{
public:

	CFilterKillCamera()
	{     
		m_nID = ePFX_FilterKillCamera;

		AddParamBool("FilterKillCamera_Active", m_pActive, 0);
		AddParamFloat("FilterKillCamera_GrainStrength", m_pGrainStrength, 0.0f);
		AddParamVec4("FilterKillCamera_ChromaShift", m_pChromaShift, Vec4(0.25f, 0.125f, 0.025f, 1.0f)); // xyz = offset, w = strength
		AddParamVec4("FilterKillCamera_Vignette", m_pVignette, Vec4(1.0f, 1.0f, 0.5f, 1.4f)); // xy = screen scale, z = radius, w = blind noise vignette scale
		AddParamVec4("FilterKillCamera_ColorScale", m_pColorScale, Vec4(1.0f, 1.0f, 1.0f, 1.0f));
		AddParamVec4("FilterKillCamera_Blindness", m_pBlindness, Vec4(0.5f, 0.5f, 1.0f, 0.7f)); // x = blind duration, y = blind fade out duration, z = blindness grey scale, w = blind noise min scale
	
		m_blindTimer = 0.0f;
	}

	virtual int Initialize();
	virtual bool Preprocess();
	virtual void Render();  
	virtual void Reset(bool bOnSpecChange = false);

	virtual const char *GetName() const
	{
		return "FilterKillCamera";
	}

private:

	CCryNameTSCRC m_techName;
	CCryNameR m_paramName;

	CEffectParam* m_pGrainStrength;
	CEffectParam*	m_pChromaShift;
	CEffectParam* m_pVignette;
	CEffectParam* m_pColorScale;
	CEffectParam* m_pBlindness;
	float					m_blindTimer;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CNanoGlass: public CPostEffect
{
public:

	struct SRenderData
	{
		SRenderData()
		{
			pRenderElement = NULL;
			pRenderObject = NULL;
		}

		const CRendElementBase *pRenderElement;
		const CRenderObject *pRenderObject;
	};

	CNanoGlass()
	{     
		m_nID = ePFX_NanoGlass;
		m_pHexOutline = NULL;
		m_pHexNormal = NULL;
		m_pNoise = NULL;
		m_noiseTime = 0.0f;
		m_time = 0.0f;

		AddParamBool("NanoGlass_Active", m_pActive, 0);
		AddParamFloat("NanoGlass_Alpha",m_pEffectAlpha,0.0f);
		AddParamFloat("NanoGlass_StartAnimPos",m_pStartAnimPos,0.0f);
		AddParamFloat("NanoGlass_EndAnimPos",m_pEndAnimPos,0.0f);
		AddParamFloat("NanoGlass_Brightness",m_pBrightness,1.0f);

		AddParamVec4("NanoGlass_Movement0", m_pMovement[0], Vec4(0.0f, 0.0f, 0.0f, 0.0f)); // x = timeSpeed, y = waveStrength, z = movementStretchScale, w = movementWaveFrequency
		AddParamVec4("NanoGlass_Movement1", m_pMovement[1], Vec4(0.0f, 0.0f, 0.16f, 0.0f)); // x = movementStrengthX, y = movementStrengthY, z = noiseSpeed, w = vignetteStrength
		AddParamVec4("NanoGlass_Filter", m_pFilter, Vec4(0.0f, 0.0f, 0.0f, 0.0f)); // x = outlineStrength, y = mistAlpha, z = refractionScale, w = bBlurRefraction
		AddParamVec4("NanoGlass_HexColor", m_pHexColor, Vec4(0.0f, 0.0f, 0.0f, 1.0f)); // xyz = Hex color, w = Hex color strength
		AddParamVec4("NanoGlass_Hex", m_pHexParams, Vec4(35.0f, 0.3f, 0.1f, 10.0f)); // x = hexTexScale, y = hexOutlineMin, z = vignetteTexOffset, w = vignetteSaturation
		AddParamVec4("NanoGlass_Vignette", m_pVignette, Vec4(1.55f, 1.2f, 0.0f, 0.0f)); // xy = vignetteScreenScale , zw = free

		m_nRenderFlags = PSP_UPDATE_BACKBUFFER;

		m_paramName = "psParams";
		m_shaderTechName = "NanoGlass";
		m_viewProjMatrixParamName = "mViewProj";
	}

	virtual int CreateResources();
	virtual void Release();
	virtual bool Preprocess();
	virtual void Render();  
	virtual void Reset(bool bOnSpecChange = false);

	virtual const char *GetName() const
	{
		return "NanoGlass";
	}

	virtual void OnBeginFrame()
	{
		const uint32 nThreadID = gRenDev->m_RP.m_nFillThreadID;
		if( SRendItem::m_RecurseLevel[nThreadID] == 0 )
			m_pRenderData[nThreadID].pRenderElement = NULL;
	}

	virtual void AddRE( const CRendElementBase *pRE, const SShaderItem *pShaderItem, CRenderObject *pObj);	

private:

	void RenderPass(bool bDebugPass); 

	SRenderData m_pRenderData[RT_COMMAND_BUF_COUNT];

	CCryNameTSCRC m_shaderTechName;
	CCryNameR m_paramName;
	CCryNameR m_viewProjMatrixParamName;

	float				m_time;
	float				m_noiseTime;

	CTexture*		m_pHexNormal;
	CTexture*		m_pHexOutline;
	CTexture*		m_pNoise;

	CEffectParam* m_pEffectAlpha;
	CEffectParam* m_pStartAnimPos;
	CEffectParam* m_pEndAnimPos;
	CEffectParam* m_pBrightness;

	CEffectParam* m_pVignette;
	CEffectParam* m_pMovement[2];
	CEffectParam* m_pFilter;
	CEffectParam* m_pHexColor;
	CEffectParam* m_pHexParams;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CHUDHitEffect: public CPostEffect
{
	//inspiration: 
	//Bioshock Inifinite @see http://www.gametrailers.com/video/ten-minute-demo-bioshock-infinite/704932?type=flv
	//Modern Warface 2 @see http://www.youtube.com/watch?v=UGV9TNcdHaA				-> bokeh
	//Halo: Reach @see http://www.youtube.com/watch?v=0ZNhC1onduY&feature=related	-> "shield" effect	http://www.youtube.com/watch?v=Lzft2MUOALo&feature=channel
	//Killzone 2: @see http://www.youtube.com/watch?v=okMqAvvC1ZU&feature=related	-> fade to alpha
	//but with fractal blood texture
	//might be pixelized blood texture
public:
	struct SHitImpact
	{
		bool	_bStarted;
		float	_fCumulTime;		
		float	_fStrength;		
		float	_fImpactSpeed;
		Vec4	_vHitDirection;
		Vec4	_vCurrentPosition;
		Vec4	_vFlashPosition;
		float	_fFlashDrawTime;
		bool	_bFlashPosInited;

		SHitImpact(float fStrength = 0, float fImpactSpeed = 0, const Vec4& vHitDirection = Vec4(0.0f, 0.0f, 0.0f, 0.0f));
	};
	static const uint32 sm_HitImpactCount = 8;

public:

	CHUDHitEffect();
	~CHUDHitEffect();
	virtual int		CreateResources();
	virtual void	Release();
	virtual bool	Preprocess();
	virtual void	Render();	
	virtual void	Reset(bool bOnSpecChange = false);
	virtual void	Update();

	virtual const char *GetName() const
	{
	  return "HUDHitEffect";
	}

	virtual void OnBeginFrame()
	{
		const uint32 nThreadID = gRenDev->m_RP.m_nFillThreadID;
		m_pRenderData[nThreadID].pRenderElement = NULL;
	}

	virtual void AddRE( const CRendElementBase *pRE, const SShaderItem *pShaderItem, CRenderObject *pObj);

protected:
	//update logic
	void	UpdateEffectLogic();
	void	SpawnHitEffect();
	void	UpdateCoverage();
	void	UpdateHealth();

	//display logic
	//bool	CreateDynTextures();
	//void	ReleaseDynTextures();
	bool	InitDynTexture(CTexture*& ptexRT, int nWidth, int nHeight);
	void	RenderAttenuationPass(CTexture*& rptexPrevRT, int iViewportWidth, int iViewportHeight, int iRTWidth, int iRTHeight);
	void	RenderAccumulationPass(int iViewportWidth, int iViewportHeight, int iRTWidth, int iRTHeight);
	void	RenderDisplayPass(CTexture*& rptexCurrRT, int iViewportWidth, int iViewportHeight);

private:
	CEffectParam*	m_pAmount;				//float, DO NOT REMOVE, needed for flownode to work

	//time/anim params --> for tweaking, TODO: replace by constant	
	CEffectParam*	m_pDisplayTime;			//float, max time of coverage	
	CEffectParam*	m_pAnimSpeed;			//float animation speed for anim UVs

	//health level
	CEffectParam*	m_pHealthLevel;			//float, health level in [0..1]
	CEffectParam*	m_pHealthNanoOffset;	//float, offset where nano pattern begin to appear
	CEffectParam*	m_pHealthVeinsOffset;	//float, offset where veins begin to appear
	CEffectParam*	m_pColorFadeOffset;		//float, offset where colors begin to fade into b&w
	CEffectParam*	m_pNanoPatternTiling;	//float, UV tiling for nanopattern

	//hit
	CEffectParam*	m_pHitDirection;		//vec4, direction of incoming hit in (x,y,z, 1.0) <-- important, else does not get spawned
	CEffectParam*	m_pHitStrength;			//float, hit strength, controls the color of hit
	CEffectParam*	m_pHitSpeed;			//float, hit impact speed, controls the animation of hit
	CEffectParam*	m_pHitAttenuation;		//float, hit attenuation used in shader to fade out previous frames (prev - this value)
	CEffectParam*	m_pHitAttenuationBlur;	//float, hit attenuation blur scale used in shader to scale/blur out previous frames (tc * this value)
	CEffectParam*	m_pHitAreaVisibility;	//float, hit area visibility, used to disable glass effect when NanoGlass displayed

	//critical
	CEffectParam*	m_pCriticalSaturation;	//float, saturation when health critical
	CEffectParam*	m_pCriticalContrast;	//float, contrast when health critical
	CEffectParam*	m_pCriticalBrightness;	//float, brightness when health critical

	//noise
	CEffectParam*	m_pNoiseAmount;		//float, noise strength

	//screen border
	CEffectParam*	m_pScreenBorderLeft;	//float, screen border on left side
	CEffectParam*	m_pScreenBorderTop;		//float, screen border on top side
	CEffectParam*	m_pScreenBorderRight;	//float, screen border on right side
	CEffectParam*	m_pScreenBorderBottom;	//float, screen border on bottom side

	//internal values - set in update
	SHitImpact		m_aHitImpacts[sm_HitImpactCount];
	uint16			m_iActiveImpacts;
	uint16			m_iCurrent1stImpact;

	//render target	
	uint16			m_uCurrentDytex;
	bool			m_b1stFrame;

	//textures
	//attenuation pass
	CTexture*		m_ptexPerlinNoise;

	//accumulation pass
	CTexture*		m_ptexImpactRound;

	//health display pass
	CTexture*		m_ptexNanoPatternLine;	
	CTexture*		m_ptexVeinsBlood;
	CTexture*		m_ptexHealthGradient;
	CTexture*		m_ptexVignetteAreas;
	CTexture*		m_ptexBlurMask_ddn;

	//internal interpolation values
	//- xT is linear interpolated value, x = curve(xT)
	float			m_fNanoLevel, m_fNanoLevelT;		//health level when nano pattern appears
	float			m_fVeinsLevel, m_fVeinsLevelT;		//health level when veins appear
	float			m_fColorLevel, m_fColorLevelT;		//health level when color fades out	
	float			m_fTilingFactor, m_fTilingFactorT;	//tiling factor
	float			m_fFlickerFrequency, m_fFlickerFrequencyT;	//flickering frequency
	float			m_fAreaVisibility, m_fAreaVisibilityT;	//visibility of hit areas/flash areas (-> disable hits when in armour mode)
	
	CPostEffect::SRenderDataAr	m_pRenderData;


	//static variables
	static const	CCryNameTSCRC	s_tnAttenuationPass;
	static const	CCryNameTSCRC	s_tnHitAccumulationPass;
	static const	CCryNameTSCRC	s_tnFlashAccumulationPass;
	static const	CCryNameTSCRC	s_tnHealthDisplayPass;

	static const	CCryNameR		s_pnAttenuationParams;
	static const	CCryNameR		s_pnNoiseParams;

	static const	CCryNameR		s_pnHitParams;

	static const	CCryNameR		s_pnDisplayParams;
	static const	CCryNameR		s_pnHealthParams;
};


////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CScreenBlood: public CPostEffect
{
public:
	CScreenBlood()
	{	
		m_nRenderFlags = 0;
		m_nID = ePFX_eScreenBlood;		
		AddParamFloat("ScreenBlood_Amount", m_pAmount, 0.0f);  // damage amount
	}

	virtual bool Preprocess();
	virtual void Render();  
	virtual void Reset(bool bOnSpecChange = false);
	virtual const char *GetName() const
	{
		return "ScreenBlood";
	}

private:

	CEffectParam* m_pAmount;
};


////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CScreenGlassShards: public CPostEffect
{
public:
	CScreenGlassShards()
	{	
		m_nRenderFlags = 0;
		m_nID = ePFX_eScreenGlassShards;		
		AddParamFloat("GlassShards_Amount", m_pAmount, 0.0f);  // damage amount
	}

	virtual bool Preprocess();
	virtual void Render();  
	virtual void Reset(bool bOnSpecChange = false);
	virtual const char *GetName() const
	{
		return "ScreenGlassShards";
	}

private:

	CEffectParam* m_pAmount;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CPost3DRenderer: public CPostEffect
{
public:

	CPost3DRenderer()
	{     
		m_nID = ePFX_Post3DRenderer;
		
		AddParamBool("Post3DRenderer_Active", m_pActive, 0);

		m_gammaCorrectionTechName = "Post3DRendererGammaCorrection";
		m_alphaCorrectionTechName = "Post3DRendererAlphaCorrection";





		AddParamFloat("Post3DRenderer_FOVScale", m_pFOVScale, 0.5f); 
		AddParamVec4("Post3DRenderer_Ambient", m_pAmbient, Vec4(0.0f,0.0f,0.0f,0.2f) );
		
		m_nRenderFlags = 0;
	}

	virtual void Render();  
	virtual void Reset(bool bOnSpecChange = false);

	virtual const char *GetName() const
	{
		return "Post3DRenderer";
	}

private:

	CCryNameTSCRC		m_gammaCorrectionTechName;
	CCryNameTSCRC		m_alphaCorrectionTechName;





	CEffectParam*		m_pFOVScale;
	CEffectParam*		m_pAmbient;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

class CScreenFog : public CPostEffect
{
public:
	CScreenFog();
	~CScreenFog();
	virtual int		CreateResources();
	virtual void	Release();
	virtual bool	Preprocess();
	virtual void	Render();
	virtual void	Reset(bool bOnSpecChange = false);
	virtual void	Update();

	virtual const char *GetName() const
	{
		return "ScreenFog";
	}

private:
	static const Vec4	m_vDefaultColor;
	CEffectParam*	m_pAmount;	
	CEffectParam*	m_pFogColor;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////


#endif
